package UIPhoto
{
	import UIFree.ObjectEvent;
	import UIFree.uif_component;
	import UIFree.uif_ecomponent;
	
	import UIUtils.uif_matrix;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	public class uip_handles extends uif_ecomponent {
		private var _ctrlResize		: uip_ctrlHandle;
		private var _ctrlRoll		: uip_ctrlHandle;
		
		private var _pResize		: Point;
		private var _pRoll			: Object;
		private var _resizeStyle	: int;
		
		protected var _contentSize	: Point;
		
		public static const RESIZE_REAL: int = 0;
		public static const RESIZE_PROP: int = 1;
		
		public function uip_handles(parent:uif_component, images: Object, ax:int=0, ay:int=0, awidth:int=0, aheight:int=0, styleClass:String='') {
			super(parent, ax, ay, 0, 0, styleClass);
			createHandles(images);
			buttonMode 		= true;
			_resizeStyle	= RESIZE_PROP;
			resetSize(new Point(awidth, aheight));
		}
		
		protected function createHandles(images: Object): void {
			_ctrlResize 	= new uip_ctrlHandle(this, images.c_resize, doCRDown);
			_ctrlRoll 		= new uip_ctrlHandle(this, images.c_roll, doRLDown);
		}
		
		override protected function listenEvents():void {
			super.listenEvents();
			addEvent(MouseEvent.ROLL_OUT, doOut, wrapper);
			addEvent(MouseEvent.MOUSE_DOWN, doDown);
			addEvent(MouseEvent.MOUSE_UP, doCRUp, wrapper);
			addEvent(MouseEvent.MOUSE_MOVE, doCRMove, wrapper);
			addEvent(uif_component.DRAG, doDrag);
		}
		
		public function get resizeStyle(): int {
			return _resizeStyle;
		}
		
		public function set resizeStyle(a_style: int): void {
			_resizeStyle = a_style;
		}
		
		public function resetSize(a_size: Point): void {
			_contentSize = a_size.clone();
			resize(_contentSize.x, _contentSize.y);
		}
		
		public function linkControl(a_link: uif_ecomponent): void {
			function updateLink(): void {
				a_link.transform.matrix = transform.matrix;
				a_link.size = size;
			}
			a_link.addEvent(uip_events.UPDATEMATRIX, function(e: ObjectEvent): void {
				updateLink();
			}, this);
			a_link.addEvent(MouseEvent.MOUSE_DOWN, doDown);
			updateLink();
		}
		
		protected function get wrapper(): EventDispatcher {
			return stage;
		}
		
		public function get editing(): Boolean {
			return (_pResize != null) || (_pRoll != null);
		}
		
		protected function doOut(e: MouseEvent): void {
			if (!editing) {
				endDrag();
			}
		}
		
		protected function doDown(e: MouseEvent): void {
			if (!editing) 
				beginDrag(1, 1);
		}
		
		private function curCoordinates(): Object {
			var a_center: Point = transform.matrix.transformPoint(new Point(width / 2, height / 2));
			var a_pos: Point = transform.matrix.transformPoint(new Point(mouseX, mouseY));
			return {center: a_center, pos: a_pos};
		}
		
		protected function setPosNotify(): void {
			dispatchEvent(new ObjectEvent(uip_events.UPDATEMATRIX, transform.matrix));
		}
		
		protected function doDrag(e: Event): void {
			setPosNotify();
			updateCtrlRect();
		}
		
		protected function doCRDown(e: MouseEvent): void {
			_pResize = new Point(parent.mouseX, parent.mouseY);
		}
		
		protected function doCRMove(e: MouseEvent): void {
			var cur			: Point;
			var pdec		: Point;
			var rect		: Rectangle;
			var dec			: Number = 0;
			var tmp			: Rectangle;
			var prevRect	: Rectangle;
			var center		: Point;
			if (_pResize != null) {
				prevRect 	= getOuter();
				cur			= new Point(parent.mouseX, parent.mouseY);
				center		= parent.globalToLocal(localToGlobal(new Point(width / 2, height / 2)));
				if (resizeStyle == RESIZE_PROP) {
					pdec 	= _pResize.subtract(cur);
					rect 	= prevRect.clone();
					
					var v: Point = center.subtract(cur);
					dec = (Point.distance(cur, center) - Point.distance(_pResize as Point, center)) * 1.5;
					
					
					function newRect(scale: Number): Rectangle {
						var mat	: uif_matrix = new uif_matrix();
						mat.translate(-center.x, -center.y);
						mat.scale(scale, scale);
						mat.translate(center.x, center.y);
						return mat.transformRect(rect);
					}
					
					tmp = newRect((prevRect.width + dec) / prevRect.width);
				} else {
					tmp = prevRect.clone();
					tmp.inflatePoint(cur.subtract(_pResize));
				}
				
				if (tmp.width > 0) {
					position = tmp.topLeft;
					resize(tmp.width, tmp.height);
					updateCtrlRect();
					setPosNotify();
				}
				_pResize = cur;
				
			} else if (_pRoll != null) {
				var v1: Point = _pRoll.center.subtract(_pRoll.pos);
				_pRoll.pos = new Point(parent.mouseX, parent.mouseY);
				var v2: Point = _pRoll.center.subtract(_pRoll.pos);
				var angle: Number = Math.atan2(v1.x, v1.y) - Math.atan2(v2.x, v2.y);
				
				var lmat: Matrix = transform.matrix;
				lmat.translate(-_pRoll.center.x, -_pRoll.center.y);
				lmat.rotate(angle);
				lmat.translate(_pRoll.center.x, _pRoll.center.y);
				transform.matrix = lmat;
				
				setPosNotify();
			}
		}
		
		protected function doCRUp(e: MouseEvent): void {
			if (editing) {
				_pResize = null;
				_pRoll	 = null;
				if (!parent.hitTestPoint(root.mouseX, root.mouseY)) doOut(e);
			}
		}
		
		protected function updateCtrlRect(): void {
			_ctrlResize.x = width - 10;
			_ctrlResize.y = height - 10;
			
			_ctrlRoll.x = width - 10;
			_ctrlRoll.y = -10
		}
		
		override protected function updateBounds():uif_component {
			super.updateBounds();
			updateCtrlRect();
			return this;
		}
		
		protected function doRLDown(e: MouseEvent): void {
			var a_center: Point = transform.matrix.transformPoint(new Point(width / 2, height / 2));
			var a_pos: Point = transform.matrix.transformPoint(new Point(mouseX, mouseY));
			_pRoll = {center: a_center, pos: a_pos};
		}
	}
}